/***************************************************************************************************
 *Copyright(C),2010-2016,Sumscope
 *FileName	:  WideString.cpp
 *Author	:  scofined.qi
 *Version	:  1.0
 *Date		:  2016/01/12
 *Desc		:  //用于主要说明此程序文件完成的主要功能
 *Relation :
 *Others	:  //其他内容说明
 *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
 *History	:
 * //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
 ***************************************************************************************************/

#include "WideString.h"

#include <stdarg.h>

#include "BaseString.h"

namespace qb {
namespace base {

static char inline GetCaseChar(bool igoreCase, const char& c) {
  return (!igoreCase && (c >= 'A' && c <= 'Z')) ? c + 32 : c;
}

WideString::WideString() : m_string(0), m_size(0), m_capcity(INIT_CAPCITY) {
  reset();
}

WideString::WideString(const Element* str)
    : m_string(0), m_size(0), m_capcity(INIT_CAPCITY) {
  reset();
  append(str);
}

WideString::WideString(const Element* str, int len)
    : m_string(0), m_size(0), m_capcity(INIT_CAPCITY) {
  reset();
  append(str, len);
}

WideString::WideString(const WideString& bs)
    : m_string(0), m_size(0), m_capcity(INIT_CAPCITY) {
  reset();
  append(bs);
}

WideString::~WideString() { reset(); }
WideString& WideString::Format(const wchar_t* format, ...) {
  va_list args;
  int ret;
  va_start(args, format);
  const int bufsize = 1024;
  wchar_t buf[bufsize] = {0};
  memset(buf, 0, bufsize * sizeof(wchar_t));
  ret = vswprintf(buf, bufsize - 1, format, args);
  va_end(args);
  clear();
  append(buf, ret);
  return *this;
}
void WideString::expand(int size) {
  // 额外增加的1个字节使得用于字符串0强行结尾
  if (m_string && size <= m_capcity) return;
  int capcity = m_capcity + m_capcity / 2;
  capcity = capcity < INIT_CAPCITY ? INIT_CAPCITY : capcity;
  capcity = capcity < size ? size : capcity;
  capcity = (capcity / 4 + 1) * 4 - 1;
  int bytes = sizeof(Element) * (capcity + 1);
  Element* arr = new (std::nothrow) Element[capcity + 1];
  memset(arr, 0, bytes);
  if (m_size > 0) {
    memcpy(arr, m_string, m_size * sizeof(Element));
  }
  if (m_string) delete[] m_string;
  m_string = arr;
  m_capcity = capcity;
}

WideString::ThisType& WideString::operator=(Element c) { return assign(c); }

WideString::ThisType& WideString::operator=(const WideString& bs) {
  return assign(bs);
}

WideString::ThisType& WideString::operator=(const Element* str) {
  return assign(str);
}

void WideString::clear() {
  m_size = 0;
  Element e = {0};
  if (m_string) m_string[0] = 0;
}

void WideString::reset() {
  if (m_string) delete[] m_string;
  m_string = 0;
  m_size = 0;
  m_capcity = INIT_CAPCITY;
  m_null[0] = 0;
  m_null[1] = 0;
}

WideString::ThisType& WideString::assign(Element c) { return assign(&c, 1); }

WideString::ThisType& WideString::assign(const Element* str) {
  return assign(str, str ? length(str) : 0);
}

WideString::ThisType& WideString::assign(const Element* str, int len) {
  clear();
  return append(str, len);
}

WideString::ThisType& WideString::assign(const WideString::ThisType& br) {
  clear();
  append(br.m_string, br.m_size);
  return *this;
}

WideString::ThisType& WideString::append(int count, Element c) {
  if (count > 0) {
    expand(size() + count);
    for (int i = 0; i < count; i++) {
      append(c);
    }
  }
  return *this;
}
WideString::ThisType& WideString::append(Element c) { return append(&c, 1); }

WideString::ThisType& WideString::append(const Element* str) {
  return append(str, str ? length(str) : 0);
}

WideString::ThisType& WideString::append(const Element* str, int len) {
  if (str && len > 0) {
    if (!m_string || m_size + len > m_capcity) expand(m_size + len);
    memcpy(m_string + m_size, str, sizeof(Element) * len);
    m_size += len;
    m_string[m_size] = 0;
  }
  return *this;
}

WideString::ThisType& WideString::append(const WideString::ThisType& br) {
  return append(br.m_string, br.m_size);
}

WideString::ThisType& WideString::push_back(Element c) { return append(c); }

WideString::ThisType& WideString::push_back(const Element* str) {
  return append(str);
}

WideString::ThisType& WideString::push_back(const Element* str, int len) {
  return append(str, len);
}

WideString::ThisType& WideString::push_back(const WideString::ThisType& br) {
  return append(br);
}

WideString::ThisType& WideString::insert(int pos, const Element* str, int len) {
  if (str && len > 0) {
    pos = (pos < 0 || pos >= m_size) ? m_size : pos;
    if (!m_string || m_size <= 0) {
      append(str, len);
    } else if (m_size + len <= m_capcity) {
      for (int i = m_size + len - 1; i >= pos + len; i--) {
        m_string[i] = m_string[i - len];
      }
      for (int i = 0; i < len; i++) {
        m_string[i + pos] = str[i];
      }
      m_size += len;
    } else {
      ThisType temp;
      temp.expand(m_size + len);
      temp.append(m_string, pos);
      temp.append(str, len);
      temp.append(m_string, m_size - pos);
      swap(temp);
    }
  }
  return *this;
}

WideString::ThisType& WideString::erase(int pos, int len /*=1*/) {
  if (m_string && m_size > 0 && pos >= 0 && pos < m_size && len > 0) {
    for (int i = pos; i < m_size; i++) {
      m_string[i] = (i + len >= m_size) ? 0 : m_string[i + len];
    }
    if (pos < m_size) {
      int left = m_size - pos;
      m_size -= len < left ? len : left;
    }
  }
  return *this;
}

WideString::ThisType& WideString::replace(int pos, int len, const Element* str,
                                          int size) {
  if (str && size > 0 && pos >= 0 && len >= 0 && pos + len <= m_size) {
    ThisType temp;
    temp.expand(m_size - len + size);
    temp.append(m_string, pos);
    temp.append(str, size);
    temp.append(m_string + pos + len, m_size - pos - len);
    swap(temp);
  }
  return *this;
}

int WideString::find(Element c, int offset) const {
  if (m_string && m_size > 0) {
    for (int i = offset; i < m_size; i++) {
      if (m_string[i] == c) return i;
    }
  }
  return npos;
}

int WideString::find(const Element* str, int offset) const {
  if (!m_string || m_size <= 0) return npos;
  if (offset < 0 || offset >= m_size) return npos;
  int len = str ? length(str) : 0;
  if (len <= 0) return npos;
  if (len + offset > m_size) return npos;
  int pos = SearchString(m_string + offset, m_size - offset, str, len, false);
  pos = pos >= 0 ? (pos + offset) : pos;
  return pos;
}

int WideString::rfind(Element c, int offset) const {
  if (m_string && m_size > 0) {
    for (int i = m_size - 1; i >= 0; i--) {
      if (m_string[i] == c) return i;
    }
  }
  return npos;
}

void WideString::substr(int offset, int len, WideString::ThisType& bs) const {
  bs.clear();
  if (m_string && m_size > 0 && len > 0) {
    int pos = offset < 0 ? 0 : offset;
    int size = (pos + len) > m_size ? (m_size - pos) : len;
    bs.append(m_string + pos, size);
  }
}

WideString::ThisType WideString::substr(int offset, int len) const {
  ThisType bs;
  substr(offset, len, bs);
  return bs;
}

int WideString::compare(const Element* str, int len) const {
  if (!str || len <= 0) return size() <= 0 ? 0 : 1;  // 有值为大
  if (size() <= 0) return (!str || len <= 0) ? 0 : -1;

  // 字典排序
  int cmp = len < size() ? len : size();
  int ret = wmemcmp(m_string, str, cmp);
  if (ret == 0) return len == size() ? 0 : (cmp == len ? 1 : -1);
  return ret;
}

void WideString::swap(WideString& bs) {
  Element* tempstr = bs.m_string;
  int tempsize = bs.m_size;
  int tempcap = bs.m_capcity;

  bs.m_string = m_string;
  bs.m_size = m_size;
  bs.m_capcity = m_capcity;

  m_string = tempstr;
  m_size = tempsize;
  m_capcity = tempcap;
}

qb::base::WideString::Element WideString::at(int i) const {
  return m_string[i];
}

WideString::Element& WideString::at(int i) { return m_string[i]; }

////////////////////////////////////////////////////////////////////////////////
int WideString::SearchString(const Element* mainStr, int mainStrLen,
                             const Element* subStr, int subStrLen, bool ic) {
  mainStrLen *= 2;
  subStrLen *= 2;
  int pos = BaseString::SearchString((const char*)mainStr, mainStrLen * 2,
                                     (const char*)subStr, subStrLen * 2, ic);
  return pos >= 0 ? pos / 2 : pos;
}

WideString& operator+=(WideString& bs, const WideString::Element* str) {
  return bs.append(str);
}
WideString& operator+=(WideString& bs, const WideString& plus) {
  return bs.append(plus);
}
bool operator<(const WideString& left, const WideString& right) {
  return left.compare(right.c_str(), right.size()) < 0;
}

}  // namespace base
}  // namespace qb
